﻿#pragma once

#include "df.h"

#include "df_net.h"



#if defined(_WIN32) || defined(_WIN32_WCE) || defined(WIN32)
#   pragma comment(lib,"libmysql")
#endif

namespace df
{

#include "mysql-6.0.2/include/mysql.h"

	class MySqlCon
	{
	public:

		void Init(CC data = "test", CC host = "127.0.0.1", CC id = "root", CC psw = "root", uint32_t port = 3306, CC coding = "utf8")
		{
			host_ = host;
			user_ = id;
			psw_ = psw;
			dbName_ = data;
			coding_ = coding;
			port_ = port;
		}

		MySqlCon(CC data = "test", CC host = "127.0.0.1", CC id = "root", CC psw = "root", uint32_t port = 3306, CC coding = "utf8")
			:fieldCount_(0)
		{

			mysql_init(&con_);

			host_ = host;
			user_ = id;
			psw_ = psw;
			dbName_ = data;
			coding_ = coding;
			port_ = port;
		}

		inline ~MySqlCon(void)
		{
			Close();
		}


		///连接数据库,返回是否成功
		bool Open(int timeOut = 15)
		{
			mysql_options(&con_, MYSQL_SET_CHARSET_NAME, coding_.char_);
			mysql_options(&con_, MYSQL_OPT_CONNECT_TIMEOUT, &timeOut);

			if (mysql_real_connect(&con_, host_.char_, user_.char_, psw_.char_, dbName_.char_, port_, "NULL", 0) == 0)
			{
				DF_ERR("Host=" << host_ << " ID=" << user_ << " PSW=" << psw_ << " DataBase=" << dbName_ << " Port=" << port_ << "\r\n" << mysql_error(&con_));
				return false;
			}

			return true;
		}

		inline void Close()
		{
			mysql_close(&con_);
		}


		///更新语句,返回影响行数,-1出错
		long long Update(const sdf::CCa & str)
		{
			if (mysql_query(&con_, str.char_))
			{
				DF_ERR(str << "\r\n" << mysql_error(&con_));
				return -1;
			}
			return mysql_affected_rows(&con_);
		}


		//*******************************************
		// Summary : 查询,返回结果结果个数
		// Parameter - const char * str : sql语句
		// Parameter - const LambdaT & func : 回调函数:bool(char**)或void(char**),返回false中断查询
		// Returns - int : -1出错
		//*******************************************
		template<class LambdaT>
		long long Select(const sdf::CCa & str, const LambdaT & func)
		{
			fieldCount_ = 0;
			if (mysql_query(&con_, str.char_))
			{
				DF_ERR(str << "\r\n" << mysql_error(&con_));
				return -1;
			}
			///select 结果
			MYSQL_RES * res = mysql_store_result(&con_);
			if (res == NULL)
			{
				DF_ERR(str << "\r\n" << mysql_error(&con_));
				return -1;
			}
			ON_SCOPE_EXIT({
				mysql_free_result(res);
			});

			fieldCount_ = res->field_count;
			///res的行结果
			MYSQL_ROW row = NULL;

			//行计数
			long long count = 0;
			while ((row = mysql_fetch_row(res)) != NULL)
			{
				count++;
				selectRes_ = row;
				if (!df::ExecuteFunctor(func))
					return count;
			}
			return count;
		}

		char* operator[](int i) const
		{
			return selectRes_[i];
		}

		char** begin() const
		{
			return selectRes_;
		}

		char** end() const
		{
			return selectRes_ + fieldCount_;
		}


		bool SelectDb(const sdf::CCa & str)
		{
			int res = mysql_select_db(&con_, str.char_);
			if (res != 0)
			{
				DF_ERR("select db " << str << "failed!\r\n" << mysql_error(&con_));
				return false;
			}
			return true;
		}
		//检测是否联通;
		inline bool Ping()
		{
			return !mysql_ping(&con_);
		}

		int GetFieldCount() const
		{
			return fieldCount_;
		}

		const char * GetLastErr()
		{
			return mysql_error(&con_);
		}

	private:



		//数据库句柄
		MYSQL con_;

		///res字段数
		int fieldCount_;
		char ** selectRes_;
		///主机
		CC host_;
		//用户
		CC user_;
		//密码
		CC psw_;
		//数据库
		CC  dbName_;
		//程序编码
		CC  coding_;
		//端口
		uint32_t port_;

		DF_DISABLE_COPY_ASSIGN(MySqlCon);
	};

}

